
#include <assert.h>
#include <stdlib.h>

int pup_vector_expand_(pup_vector_t* __restrict__ vector, size_t min_capacity);

static inline int pup_vector_init(pup_vector_t* __restrict__ vector)
{
  if (vector) {
    vector->begin = NULL;
    vector->end = NULL;
    vector->alloc_end = NULL;
    return 0;
  } else {
    return -1;
  }
}

static inline int pup_vector_uninit(pup_vector_t* __restrict__ vector)
{
  if (vector->begin)
    free(vector->begin);
  return 0;
}

static inline size_t pup_vector_capacity(pup_vector_t const* __restrict__ vector)
{
  return vector->alloc_end - vector->begin;
}

static inline bool pup_vector_empty(pup_vector_t const* __restrict__ vector)
{
  return vector->begin == vector->end;
}

static inline int pup_vector_reserve(pup_vector_t* __restrict__ vector, size_t capacity)
{
  if (capacity > pup_vector_capacity(vector))
    return pup_vector_expand_(vector, capacity);
  else
    return 0;
}

static inline int pup_vector_resize(pup_vector_t* __restrict__ vector, size_t size)
{
  size_t const current_size = pup_vector_size(vector);
  if (size > current_size) {
    if (!pup_vector_reserve(vector, size))
      return -1;
  }
  vector->end = vector->begin + size;
  return 0;
}

static inline size_t pup_vector_size(pup_vector_t const* __restrict__ vector)
{
  return vector->end - vector->begin;
}

static inline pup_item_t const* pup_vector_begin_const(pup_vector_t const* __restrict__ vector)
{
  return vector->begin;
}

static inline pup_item_t const* pup_vector_end_const(pup_vector_t const* __restrict__ vector)
{
  return vector->end;
}

static inline pup_item_t* pup_vector_begin(pup_vector_t* __restrict__ vector)
{
  return vector->begin;
}

static inline pup_item_t* pup_vector_end(pup_vector_t* __restrict__ vector)
{
  return vector->end;
}

static inline pup_item_t* 
pup_vector_at_index(pup_vector_t* __restrict__ vector, size_t index)
{
  assert(index < pup_vector_size(vector));
  return vector->begin + index;
}

static inline pup_item_t const* 
pup_vector_at_index_const(pup_vector_t const* __restrict__ vector, size_t index)
{
  assert(index < pup_vector_size(vector));
  return vector->begin + index;
}

static inline int 
pup_vector_push_back(pup_vector_t* __restrict__ vector, pup_item_t item)
{
  if (vector->end == vector->alloc_end && pup_vector_expand_(vector, pup_vector_size(vector)*2))
    return -1;
  *(vector->end++) = item;
  return 0;
}


